/**
 * @author cmtlyt
 * @version v1.0
 */

package chapter02;

/*
 java定义变量的格式: 数据类型 变量名 = 变量值;

 声明: 告诉编译器,我有一个什么东西
 定义: 告诉编译器,这个东西他是干什么的,或者说它是什么

 java定义的数据类型:
  基本数据类型:
   整数类型: byte / short / int / long
   浮点类型: float / double
   字符型 char
   布尔型 boolean
  引用数据类型:
   类 class (字符串在这里)
   接口 interface
   数组 []

 attention: 
  1. 变量必须先声明再使用
  2. 变量定义再他的作用域内,作用域内,他是有效的,出了作用域,就不能用了
  3. 数值类型的变量类型自动提升的时候是从小到大的,这里的大小不是说占用内存的大小,是表示数字的大小
  4. 整型的常量,默认类型为int
  5. 浮点型的常量,默认类型为double

 warning:
  1. 变量使用之前必须先定义!!!
  2. 同一个作用域内,不可以声明两个同名的变量
*/

public class Variable {
 public static void main(String[] args) {
  // 变量定义
  int myAge = 12;
  System.out.println(myAge);

  // 使用myNumber之前没有定义myNumber,所以这里编译的时候会报错
  // System.out.println(myNumber);
  // 变量声明
  int myNumber;
  // 这里也是,myNumber没有被定义,所以也会报错
  // System.out.println(myNumber);
  // 变量赋值(定义)
  myNumber = 123;
  System.out.println(myNumber);

  // 整数
  // byte
  byte b1 = 12;
  byte b2 = -128;
  // 超过了存储范围,这里会报错
  // byte b3 = 128;
  // byte b4 = -129;
  System.out.printf("%d, %d\n", b1, b2);
  // short
  short s1 = 128;
  // int 通常定义整型变量的时候都会使用int
  int i1 = 1234;
  // long 定义long变量的时候必须要用l或者L结尾
  long l1 = 1234567L;
  System.out.printf("%d, %d, %d\n", s1, i1, l1);

  // 浮点型
  // float 精确到小数点后7位有效数字,定义float类型的变量的时候必须要用f或者F结尾
  float f1 = 123.123f;
  // double 精度时float的两倍,通常定义浮点型变量的时候都会使用double
  double d1 = 123456.123456;
  System.out.printf("%f, %f\n", f1, d1);

  // 字符类型
  // char 定义char类型变量的时候要使用单引号包裹
  char c1 = 'a';
  char c2 = '中';
  char c3 = '₪';
  char c4 = '\ud83d';
  char c5 = '\n';
  System.out.printf("%c, %c, %c, %c%c", c1, c2, c3, c4, c5);

  // 布尔型
  // boolean 只能取true和false两个值之一
  boolean bl1 = true;
  System.out.printf("%b", bl1);

  // ===================================
  // 基本数据类型之间的运算规则
  // 前提: 只讨论7中基本数据类型之间的运算,不包含boolean类型的
  // 自动类型提升
  byte ab1 = 2;
  int ai1 = 129;
  // 编译不通过,因为byte和int相加的话,会自动变成int类型,所以用byte类型的变量存储会出错
  // byte ab2 = ab1 + ai1;
  int ai2 = ab1 + ai1;
  long al1 = ab1 + ai1;
  System.out.printf("%d, %d", ai2, al1);
  float af1 = ab1 + ai1;
  System.out.println(af1);
  short as1 = 123;
  double ad1 = as1;
  System.out.println(ad1);
  // 变量类型自动提升的时候是从小到大的,这里的大小不是说占用内存的大小,是表示数字的大小
  char bc1 = 'a';
  int bi1 = 19;
  int bi2 = bc1 + bi1;
  System.out.println(bi2);
  // 编译不通过,因为char提升过后是int所以short不能用来存储int
  // short bs2 = bc1 + bi1;
  // 当byte,char,short三种类型的变量做运算时,结果为int

  // ===================================
  // 强制类型转换
  double cd1 = 12.4;
  // 编译不通过,因为int存储不表double的变量
  // int ci1 = cd1;
  // 手动强制把double转成int
  int ci1 = (int) cd1;
  System.out.println(ci1);
  long cl1 = 123;
  // short cs2 = cl1; 错误同上
  short cs2 = (short) cl1;
  System.out.println(cs2);
  int ci2 = 120;
  byte cb1 = (byte) ci2;
  System.out.println(cb1);

  // 特殊情况
  // 编码
  long dl1 = 123123;
  System.out.println(dl1);
  // 编译失败: 过大的整数
  // long dl2 = 123123123123123123;
  // 如果不加l或者L的话编译器就会把这个常量当成int,但是int存储不了这么大的数字,所以会报错
  long dl2 = 123123123123123123L;
  System.out.println(dl2);
  // 编译失败,float定义的时候必须加f,不加的话直接就会报错
  // float df1 = 12.3;
  float df1 = 12.3f;
  float df2 = (float) 12.3;
  System.out.printf("%f, %f", df1, df2);
 }
}
